<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Guacamole from "guacamole-common-js";
import { ElMessage } from "element-plus";
import HelpFilled from "@iconify-icons/ep/help-filled";
import CloseBold from "@iconify-icons/ep/close-bold";
import StackshareLine from "@iconify-icons/ri/stackshare-line";
import ShareLine from "@iconify-icons/ri/share-line";
import StrikethroughIcon from "@iconify-icons/ri/strikethrough";

defineOptions({
  name: "MointorPage"
});

const toolbarB = ref(false);

const showMenu = ref(false);

const clickToolbar = () => {
  toolbarB.value = !toolbarB.value;
  showMenu.value = !showMenu.value;
};

const desktopObj = {
  client: undefined,
  layer: undefined,
  state: 0,
  sink: undefined
};

onMounted(() => {
  setTimeout(function () {
    wsHandshake();
    // // 监听窗口大小变化，执行窗口重绘操作
    // window.addEventListener('resize', onWindowResize)
    // window.onfocus = onWindowFocus
  }, 1);
});
const getQueryParams = (url: string) => {
  const paramArr = url.slice(url.indexOf("?") + 1).split("&");
  const params = new Map();
  paramArr.map(param => {
    const [key, val] = param.split("=");
    params.set(key, decodeURIComponent(val));
  });
  return params;
};
const websocketPath = "ws://" + import.meta.env.VITE_API_URI + "/api/vap";
const wsHandshake = () => {
  const param = getQueryParams(window.location.href);
  const params = "id=" + param.get("id");
  // todo 设置虚拟机剪贴板内容
  const tunnel = new Guacamole.WebSocketTunnel(
    websocketPath + "/session/gua/monitor"
  );
  // 创建桌面客户端
  desktopObj.client = new Guacamole.Client(tunnel);
  // 解析自定义指令，这行代码必须放到  new Guacamole.Client(tunnel) 代码之后
  const _oninstruction = tunnel.oninstruction;
  tunnel.oninstruction = function (opcode, parameters) {
    onTunnelInstruction(opcode, parameters);
    if (_oninstruction) {
      _oninstruction(opcode, parameters);
    }
  };

  desktopObj.client.onerror = onClientError;
  // 处理客户端的状态变化事件
  desktopObj.client.onstatechange = onClientStateChange;

  const display = document.getElementById("monitor");
  desktopObj.layer = desktopObj.client.getDisplay();
  const element = desktopObj.client.getDisplay().getElement();
  display.appendChild(element);
  desktopObj.client.connect(params);
  // 页面关闭时销毁客户端对象
  window.onunload = function () {
    desktopObj.client.disconnect();
  };
};

const clickJoin = () => {
  const display = document.getElementById("monitor");
  const element = desktopObj.client.getDisplay().getElement();
  display.appendChild(element);
  // mouse
  const mouse = new Guacamole.Mouse(element);
  mouse.onmousedown =
    mouse.onmouseup =
    mouse.onmousemove =
      function (mouseState: any) {
        const ms = new Guacamole.Mouse.State(
          mouseState.x / desktopObj.layer.getScale(),
          mouseState.y / desktopObj.layer.getScale(),
          mouseState.left,
          mouseState.middle,
          mouseState.right,
          mouseState.up,
          mouseState.down
        );
        desktopObj.client.sendMouseState(ms);
      };
  // sink
  desktopObj.sink = new Guacamole.InputSink();
  display.appendChild(desktopObj.sink.getElement());
  desktopObj.sink.focus();

  // Keyboard
  const keyboard = new Guacamole.Keyboard(desktopObj.sink.getElement());
  keyboard.onkeydown = onKeyDown;
  keyboard.onkeyup = onKeyUp;
};

const clickRelease = () => {
  // mouse
  desktopObj.client.sendMouseState = null;
  desktopObj.client.sendKeyEvent = null;
};

const clickTakeOver = () => {
  ElMessage({
    message:
      "通知其他客户端释放鼠键，原始客户端只能看，不能操作，这个功能可能不合理，后面再说",
    type: "warning"
  });
};

const onClientError = (state: any) => {
  console.log("onClientError", state);
};
const onClientStateChange = (state: any) => {
  console.log("onClientStateChange", state);
};
const onTunnelInstruction = (opcode: any, parameters: any) => {
  if (opcode == "hint") {
    ElNotification({
      title: decodeURI(parameters[0]),
      message: decodeURI(parameters[1]),
      type: parameters[2],
      duration: 0
    });
  }
  if (opcode == "disconnect") {
    console.log("连接销毁，画面关闭");
  }
  if (opcode == "error") {
    console.error("指令", opcode, "参数", parameters);
    desktopObj.client.disconnect();
  }
};
const onKeyUp = keySym => {
  desktopObj.client.sendKeyEvent(0, keySym);
};
const onKeyDown = keySym => {
  console.log(keySym);
  desktopObj.client.sendKeyEvent(1, keySym);
  if (keySym === 65288) {
    return false;
  }
};
</script>

<template>
  <div id="monitor" class="desktop-div" />
  <div class="toolbar-div">
    <div>
      <Transition>
        <div v-show="showMenu" class="toolbar-menu">
          <el-tooltip effect="dark" content="协同" placement="left-start">
            <el-button
              class="toolbar-btn"
              size="large"
              :icon="useRenderIcon(StackshareLine)"
              @click="clickJoin"
              circle
            />
          </el-tooltip>
          <el-tooltip effect="dark" content="接管" placement="left-start">
            <el-button
              class="toolbar-btn"
              size="large"
              :icon="useRenderIcon(ShareLine)"
              circle
              @click="clickTakeOver"
            />
          </el-tooltip>
          <el-tooltip effect="dark" content="释放" placement="left-start">
            <el-button
              class="toolbar-btn"
              size="large"
              :icon="useRenderIcon(StrikethroughIcon)"
              @click="clickRelease"
              circle
            />
          </el-tooltip>
        </div>
      </Transition>
      <el-button
        @click="clickToolbar"
        class="toolbar-btn"
        type="primary"
        :icon="toolbarB ? useRenderIcon(CloseBold) : useRenderIcon(HelpFilled)"
        size="large"
        circle
      />
    </div>
  </div>
</template>

<style scoped>
.desktop-div {
  width: 100%;
  height: 100%;
}

.toolbar-div {
  position: fixed;
  bottom: 10px;
  right: 10px;
}

.toolbar-menu {
  width: 40px;
}

.toolbar-btn {
  font-size: 24px;
  margin-left: 0px;
}
</style>
